﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.WowAddonStudio.TocEditor;
using NUnit.Framework;

namespace WowProjectPackage.Tests.TocEditor
{
	[TestFixture]
	public class TocDocumentTest
	{
		private TocDocument document;
		private IFileListManager fileManager;
		private IMetadataManager metaManager;

		private string sourceFile;
		private string targetFile;
		private string addExtendedResult;
		private string deleteBasicTagResult;
		private string excludeFileResult;
		private string includeFileResult;
		private string moveFileResult;
		private string abakusTocFile;

		/// <summary>
		/// Sets up.
		/// </summary>
		[SetUp]
		public void SetUp()
		{
			sourceFile = Path.Combine(Environment.CurrentDirectory, @"TocEditor\TestData\Test.toc");
			targetFile = Path.Combine(Environment.CurrentDirectory, @"TocEditor\TestData\Test1.toc");
			addExtendedResult = Path.Combine(Environment.CurrentDirectory, @"TocEditor\TestData\AddExtendedTagResult.toc");
			deleteBasicTagResult = Path.Combine(Environment.CurrentDirectory, @"TocEditor\TestData\DeleteBasicTagResult.toc");
			excludeFileResult = Path.Combine(Environment.CurrentDirectory, @"TocEditor\TestData\ExcludeFileResult.toc");
			includeFileResult = Path.Combine(Environment.CurrentDirectory, @"TocEditor\TestData\IncludeFileResult.toc");
			moveFileResult = Path.Combine(Environment.CurrentDirectory, @"TocEditor\TestData\MoveFileResult.toc");
			abakusTocFile = Path.Combine(Environment.CurrentDirectory, @"TocEditor\TestData\Abakus.toc");

			if (File.Exists(targetFile))
				File.Delete(targetFile);

			document = new TocDocument();
			document.Read(sourceFile);
			var furtherFiles = new List<string> {"Action.mp3"};
			fileManager = new FileListManager(document, furtherFiles);
			metaManager = new MetadataManager(document);
		}

		/// <summary>
		/// Tears down.
		/// </summary>
		[TearDown]
		public void TearDown()
		{
			if (File.Exists(targetFile))
				File.Delete(targetFile);
		}

		/// <summary>
		/// Adds the extended tag.
		/// </summary>
		[Test]
		public void AddExtendedTag()
		{
			metaManager["X-Added"] = "24/04/08";
			document.Write(targetFile);
			AssertEqualContent(targetFile, addExtendedResult);
		}

		/// <summary>
		/// Deletes the basic tag.
		/// </summary>
		[Test]
		public void DeleteBasicTag()
		{
			metaManager.Remove(TocTagName.Interface);
			document.Write(targetFile);
			AssertEqualContent(targetFile, deleteBasicTagResult);
		}

		/// <summary>
		/// Excludes the file.
		/// </summary>
		[Test]
		public void ExcludeFile()
		{
			fileManager.ChangeIncludeState(
				fileManager.Files.First(repr => repr.RelativePath == @"Libs\AceAddon-2.0\AceAddon-2.0.lua"));
			OnChanged();
			document.Write(targetFile);
			AssertEqualContent(targetFile, excludeFileResult);
		}

		/// <summary>
		/// Includes the file.
		/// </summary>
		[Test]
		public void IncludeFile()
		{
			IFileRepresentation fr = fileManager.Files.First(repr => repr.RelativePath == @"Action.mp3");
			fileManager.ChangeIncludeState(fr);
			OnChanged();
			document.Write(targetFile);
			AssertEqualContent(targetFile, includeFileResult);
		}

		/// <summary>
		/// Moves the file.
		/// </summary>
		[Test]
		public void MoveFile()
		{
			IFileRepresentation fr = fileManager.Files.First(repr => repr.RelativePath == @"WowAddon82.lua");
			fileManager.MoveDown(fr);
			fileManager.MoveDown(fr);
			OnChanged();
			document.Write(targetFile);
			AssertEqualContent(targetFile, moveFileResult);
		}

		/// <summary>
		/// Testing bugfix for import. Metadata lines with additional # characters
		/// could not be read and caused a crash earlier.
		/// </summary>
		[Test]
		public void ReadAbakusAddonTocFile()
		{
			var document = new TocDocument();
			document.Read(abakusTocFile);
			Assert.AreEqual(document.Files.Count, 1);
			Assert.AreEqual(document.Tags.GetTags().Count(), 7);
		}

		/// <summary>
		/// Called when [changed].
		/// </summary>
		private void OnChanged()
		{
			document.Files.Clear();

			foreach (var file in fileManager.Files)
			{
				if (file.IsIncluded)
					document.Files.Add(file.RelativePath);
			}
		}

		/// <summary>
		/// Asserts the content of the equal.
		/// </summary>
		/// <param name="targetFile">The target file.</param>
		/// <param name="addExtendedResult">The add extended result.</param>
		private static void AssertEqualContent(string targetFile, string addExtendedResult)
		{
			using (StreamReader target = File.OpenText(targetFile))
			{
				using (StreamReader expected = File.OpenText(addExtendedResult))
				{
					string result = target.ReadToEnd();
					string expectedResult = expected.ReadToEnd();

					Assert.AreEqual(result, expectedResult);
				}
			}
		}
	}
}